package com.personalink.input.service;

import com.personalink.input.dto.InputProcessResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.tika.Tika;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;

/**
 * 图像处理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ImageProcessService {
    
    private final Tika tika = new Tika();
    
    // 支持的图像格式
    private static final Set<String> SUPPORTED_FORMATS = Set.of(
            "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp"
    );
    
    // 最大文件大小 (10MB)
    private static final long MAX_FILE_SIZE = 10 * 1024 * 1024;
    
    /**
     * 处理图像输入
     */
    public InputProcessResult processImage(MultipartFile file, String userId, String sessionId, String description) {
        validateImageFile(file);
        
        log.info("开始处理图像，文件名: {}, 大小: {} bytes", file.getOriginalFilename(), file.getSize());
        
        try {
            // 读取图像
            BufferedImage image = ImageIO.read(file.getInputStream());
            if (image == null) {
                throw new IllegalArgumentException("无法读取图像文件");
            }
            
            // 图像分析
            InputProcessResult.ImageAnalysis analysis = analyzeImage(image, file);
            
            // 对象检测
            List<InputProcessResult.ExtractedObject> objects = detectObjects(image);
            
            return InputProcessResult.builder()
                    .userId(userId)
                    .sessionId(sessionId)
                    .inputType("image")
                    .imageAnalysis(analysis)
                    .extractedObjects(objects)
                    .processedAt(System.currentTimeMillis())
                    .metadata(Map.of(
                            "originalFilename", file.getOriginalFilename(),
                            "fileSize", file.getSize(),
                            "contentType", file.getContentType()
                    ))
                    .build();
                    
        } catch (IOException e) {
            log.error("处理图像时发生错误", e);
            throw new RuntimeException("图像处理失败: " + e.getMessage());
        }
    }
    
    /**
     * 验证图像文件
     */
    private void validateImageFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("图像文件不能为空");
        }
        
        if (file.getSize() > MAX_FILE_SIZE) {
            throw new IllegalArgumentException("图像文件大小不能超过10MB");
        }
        
        try {
            String mimeType = tika.detect(file.getInputStream());
            if (!SUPPORTED_FORMATS.contains(mimeType)) {
                throw new IllegalArgumentException("不支持的图像格式: " + mimeType);
            }
        } catch (IOException e) {
            throw new IllegalArgumentException("无法检测文件类型");
        }
    }
    
    /**
     * 图像分析
     */
    private InputProcessResult.ImageAnalysis analyzeImage(BufferedImage image, MultipartFile file) {
        // 基本信息
        InputProcessResult.ImageDimensions dimensions = InputProcessResult.ImageDimensions.builder()
                .width(image.getWidth())
                .height(image.getHeight())
                .format(getImageFormat(file.getContentType()))
                .fileSize(file.getSize())
                .build();
        
        // 颜色分析
        InputProcessResult.ColorAnalysis colorAnalysis = analyzeColors(image);
        
        // 场景分类
        String sceneCategory = classifyScene(image);
        
        // 图像描述
        String description = generateDescription(image, sceneCategory);
        
        // 对象检测
        List<InputProcessResult.DetectedObject> objects = performObjectDetection(image);
        
        // 质量评分
        Double qualityScore = calculateImageQuality(image);
        
        return InputProcessResult.ImageAnalysis.builder()
                .description(description)
                .objects(objects)
                .sceneCategory(sceneCategory)
                .qualityScore(qualityScore)
                .dimensions(dimensions)
                .colorAnalysis(colorAnalysis)
                .build();
    }
    
    /**
     * 颜色分析
     */
    private InputProcessResult.ColorAnalysis analyzeColors(BufferedImage image) {
        Map<Integer, Integer> colorCount = new HashMap<>();
        int totalPixels = 0;
        long brightnessSum = 0;
        
        // 采样分析（避免处理所有像素）
        int step = Math.max(1, Math.min(image.getWidth(), image.getHeight()) / 100);
        
        for (int x = 0; x < image.getWidth(); x += step) {
            for (int y = 0; y < image.getHeight(); y += step) {
                int rgb = image.getRGB(x, y);
                Color color = new Color(rgb);
                
                // 简化颜色（减少颜色数量）
                int simplifiedRgb = simplifyColor(color);
                colorCount.put(simplifiedRgb, colorCount.getOrDefault(simplifiedRgb, 0) + 1);
                
                // 计算亮度
                brightnessSum += (color.getRed() + color.getGreen() + color.getBlue()) / 3;
                totalPixels++;
            }
        }
        
        // 找出主导颜色
        String dominantColor = findDominantColor(colorCount);
        
        // 生成调色板
        List<String> colorPalette = generateColorPalette(colorCount);
        
        // 计算平均亮度
        double brightness = totalPixels > 0 ? (double) brightnessSum / totalPixels / 255.0 : 0.5;
        
        // 简化的对比度计算
        double contrast = calculateContrast(image);
        
        return InputProcessResult.ColorAnalysis.builder()
                .dominantColor(dominantColor)
                .colorPalette(colorPalette)
                .brightness(brightness)
                .contrast(contrast)
                .build();
    }
    
    /**
     * 简化颜色
     */
    private int simplifyColor(Color color) {
        // 将颜色量化到较少的级别
        int r = (color.getRed() / 32) * 32;
        int g = (color.getGreen() / 32) * 32;
        int b = (color.getBlue() / 32) * 32;
        return new Color(r, g, b).getRGB();
    }
    
    /**
     * 找出主导颜色
     */
    private String findDominantColor(Map<Integer, Integer> colorCount) {
        int maxCount = 0;
        int dominantRgb = 0;
        
        for (Map.Entry<Integer, Integer> entry : colorCount.entrySet()) {
            if (entry.getValue() > maxCount) {
                maxCount = entry.getValue();
                dominantRgb = entry.getKey();
            }
        }
        
        Color color = new Color(dominantRgb);
        return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue());
    }
    
    /**
     * 生成调色板
     */
    private List<String> generateColorPalette(Map<Integer, Integer> colorCount) {
        return colorCount.entrySet().stream()
                .sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed())
                .limit(5)
                .map(entry -> {
                    Color color = new Color(entry.getKey());
                    return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue());
                })
                .toList();
    }
    
    /**
     * 计算对比度
     */
    private double calculateContrast(BufferedImage image) {
        // 简化的对比度计算
        int width = image.getWidth();
        int height = image.getHeight();
        
        if (width < 2 || height < 2) return 0.5;
        
        double totalContrast = 0;
        int comparisons = 0;
        
        // 采样计算
        int step = Math.max(1, Math.min(width, height) / 50);
        
        for (int x = 0; x < width - step; x += step) {
            for (int y = 0; y < height - step; y += step) {
                Color c1 = new Color(image.getRGB(x, y));
                Color c2 = new Color(image.getRGB(x + step, y));
                
                double brightness1 = (c1.getRed() + c1.getGreen() + c1.getBlue()) / 3.0;
                double brightness2 = (c2.getRed() + c2.getGreen() + c2.getBlue()) / 3.0;
                
                totalContrast += Math.abs(brightness1 - brightness2) / 255.0;
                comparisons++;
            }
        }
        
        return comparisons > 0 ? totalContrast / comparisons : 0.5;
    }
    
    /**
     * 场景分类
     */
    private String classifyScene(BufferedImage image) {
        // 简化的场景分类（基于颜色和纹理特征）
        InputProcessResult.ColorAnalysis colorAnalysis = analyzeColors(image);
        
        double brightness = colorAnalysis.getBrightness();
        String dominantColor = colorAnalysis.getDominantColor();
        
        // 基于颜色的简单分类
        if (brightness > 0.8) {
            return "outdoor_bright";
        } else if (brightness < 0.3) {
            return "indoor_dark";
        } else if (dominantColor.toLowerCase().contains("00ff00") || 
                   dominantColor.toLowerCase().contains("008000")) {
            return "nature";
        } else if (dominantColor.toLowerCase().contains("0000ff") || 
                   dominantColor.toLowerCase().contains("87ceeb")) {
            return "sky_water";
        } else {
            return "general";
        }
    }
    
    /**
     * 生成图像描述
     */
    private String generateDescription(BufferedImage image, String sceneCategory) {
        StringBuilder description = new StringBuilder();
        
        // 基本信息
        description.append(String.format("这是一张%dx%d像素的图像。", image.getWidth(), image.getHeight()));
        
        // 场景描述
        switch (sceneCategory) {
            case "outdoor_bright" -> description.append("图像较为明亮，可能是户外场景。");
            case "indoor_dark" -> description.append("图像较为昏暗，可能是室内场景。");
            case "nature" -> description.append("图像包含大量绿色，可能是自然风景。");
            case "sky_water" -> description.append("图像包含蓝色元素，可能包含天空或水体。");
            default -> description.append("这是一张普通的图像。");
        }
        
        return description.toString();
    }
    
    /**
     * 对象检测（简化版）
     */
    private List<InputProcessResult.DetectedObject> performObjectDetection(BufferedImage image) {
        List<InputProcessResult.DetectedObject> objects = new ArrayList<>();
        
        // 简化的对象检测（基于颜色区域）
        // 这里只是示例，实际应用中需要使用专业的对象检测模型
        
        // 检测人脸区域（简化版 - 基于肤色）
        List<InputProcessResult.BoundingBox> faceRegions = detectFaceRegions(image);
        for (InputProcessResult.BoundingBox box : faceRegions) {
            objects.add(InputProcessResult.DetectedObject.builder()
                    .label("person")
                    .confidence(0.6)
                    .boundingBox(box)
                    .build());
        }
        
        return objects;
    }
    
    /**
     * 检测人脸区域（简化版）
     */
    private List<InputProcessResult.BoundingBox> detectFaceRegions(BufferedImage image) {
        List<InputProcessResult.BoundingBox> regions = new ArrayList<>();
        
        // 简化的肤色检测
        int width = image.getWidth();
        int height = image.getHeight();
        
        for (int x = 0; x < width - 50; x += 20) {
            for (int y = 0; y < height - 50; y += 20) {
                if (isSkinColorRegion(image, x, y, 50, 50)) {
                    regions.add(InputProcessResult.BoundingBox.builder()
                            .x(x)
                            .y(y)
                            .width(50)
                            .height(50)
                            .build());
                }
            }
        }
        
        return regions;
    }
    
    /**
     * 检测是否为肤色区域
     */
    private boolean isSkinColorRegion(BufferedImage image, int startX, int startY, int width, int height) {
        int skinPixels = 0;
        int totalPixels = 0;
        
        for (int x = startX; x < Math.min(startX + width, image.getWidth()); x += 5) {
            for (int y = startY; y < Math.min(startY + height, image.getHeight()); y += 5) {
                Color color = new Color(image.getRGB(x, y));
                if (isSkinColor(color)) {
                    skinPixels++;
                }
                totalPixels++;
            }
        }
        
        return totalPixels > 0 && (double) skinPixels / totalPixels > 0.3;
    }
    
    /**
     * 判断是否为肤色
     */
    private boolean isSkinColor(Color color) {
        int r = color.getRed();
        int g = color.getGreen();
        int b = color.getBlue();
        
        // 简化的肤色检测规则
        return r > 95 && g > 40 && b > 20 && 
               r > g && r > b && 
               r - g > 15 && 
               Math.abs(r - g) > 15;
    }
    
    /**
     * 对象检测
     */
    private List<InputProcessResult.ExtractedObject> detectObjects(BufferedImage image) {
        List<InputProcessResult.ExtractedObject> objects = new ArrayList<>();
        
        // 基于图像特征的简单对象识别
        InputProcessResult.ColorAnalysis colorAnalysis = analyzeColors(image);
        
        // 基于主导颜色推断可能的对象
        String dominantColor = colorAnalysis.getDominantColor().toLowerCase();
        
        if (dominantColor.contains("00ff00") || dominantColor.contains("008000")) {
            objects.add(InputProcessResult.ExtractedObject.builder()
                    .type("vegetation")
                    .value("植物或绿色植被")
                    .confidence(0.7)
                    .attributes(Map.of("color", "green", "category", "nature"))
                    .build());
        }
        
        if (dominantColor.contains("0000ff") || dominantColor.contains("87ceeb")) {
            objects.add(InputProcessResult.ExtractedObject.builder()
                    .type("sky_water")
                    .value("天空或水体")
                    .confidence(0.6)
                    .attributes(Map.of("color", "blue", "category", "nature"))
                    .build());
        }
        
        return objects;
    }
    
    /**
     * 计算图像质量
     */
    private Double calculateImageQuality(BufferedImage image) {
        double score = 0.5; // 基础分
        
        // 分辨率评分
        int pixels = image.getWidth() * image.getHeight();
        if (pixels > 1000000) { // > 1MP
            score += 0.2;
        } else if (pixels > 300000) { // > 0.3MP
            score += 0.1;
        }
        
        // 对比度评分
        double contrast = calculateContrast(image);
        score += contrast * 0.2;
        
        // 亮度评分（避免过暗或过亮）
        InputProcessResult.ColorAnalysis colorAnalysis = analyzeColors(image);
        double brightness = colorAnalysis.getBrightness();
        if (brightness > 0.2 && brightness < 0.8) {
            score += 0.1;
        }
        
        return Math.min(score, 1.0);
    }
    
    /**
     * 获取图像格式
     */
    private String getImageFormat(String contentType) {
        if (contentType == null) return "unknown";
        
        return switch (contentType.toLowerCase()) {
            case "image/jpeg", "image/jpg" -> "JPEG";
            case "image/png" -> "PNG";
            case "image/gif" -> "GIF";
            case "image/webp" -> "WEBP";
            default -> "unknown";
        };
    }
}